package commands

import (
	"fmt"
	"os/exec"

	"github.com/spf13/cobra"
)

// NewConsoleCommand 创建控制台管理命令
func NewConsoleCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "console",
		Short: "控制台管理",
		Long:  "管理虚拟机控制台",
	}

	cmd.AddCommand(newConsoleSerialCommand())
	cmd.AddCommand(newConsoleVNCCommand())
	cmd.AddCommand(newConsoleSPICECommand())

	return cmd
}

// vmctl console serial <vm>
func newConsoleSerialCommand() *cobra.Command {
	var (
		connID      string
		interactive bool
	)

	cmd := &cobra.Command{
		Use:   "serial <vm-name>",
		Short: "Connect to serial console",
		Args:  cobra.ExactArgs(1),
		Long: `Connect to virtual machine serial console.

This command connects to the serial console of a virtual machine.
Serial console provides text-based access to the VM's console output.

In interactive mode, it will automatically connect to the WebSocket console
and provide a terminal interface for interacting with the VM.`,
		Example: `  # Display serial console information
  vmctl console serial ubuntu-vm

  # Interactive mode - connect directly to serial console
  vmctl console serial ubuntu-vm --interactive

  # With specific connection
  vmctl console serial ubuntu-vm --connection conn-id --interactive`,
		RunE: func(cmd *cobra.Command, args []string) error {
			vmName := args[0]
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			ProxyURL, WSPath, err := client.Console().GenerateConsoleURL(cmd.Context(), "serial", connID, vmName)
			if err != nil {
				fmt.Println("get url error")
				return nil
			}

			WSURL := buildWebSocketURL(client.GetServerURL(), WSPath)

			fmt.Printf("Serial Console Information:\n")
			fmt.Printf("  Proxy URL: %s\n", ProxyURL)
			fmt.Printf("  WebSocket: %s\n", WSURL)
			fmt.Println()

			if interactive {
				// 交互式模式：直接连接到 WebSocket 控制台
				if WSURL == "" {
					return fmt.Errorf("WebSocket path not available for serial console")
				}

				fmt.Println("Connecting to serial console in interactive mode...")

				// 运行 WebSocket 客户端
				return RunSerialConsole(WSURL)
			} else {
				// 非交互式模式：显示连接信息
				fmt.Println("To connect to the serial console:")
				fmt.Println("  - Use a WebSocket client to connect to the WebSocket path above")
				fmt.Println("  - Or use: vmctl console serial <vm> --interactive")
			}

			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "default", "Connection ID")
	cmd.Flags().BoolVarP(&interactive, "interactive", "i", true, "Interactive mode - connect directly to serial console")
	return cmd
}

// vmctl console vnc <vm>
func newConsoleVNCCommand() *cobra.Command {
	var (
		connID string
		viewer string
	)

	cmd := &cobra.Command{
		Use:   "vnc <vm-name>",
		Short: "Connect to VNC console",
		Args:  cobra.ExactArgs(1),
		Long: `Connect to VNC console using external viewer.

Requires a VNC viewer to be installed:
  - vncviewer (TigerVNC)
  - vinagre (GNOME)
  - krdc (KDE)
  - Remote Desktop (macOS)`,
		Example: `  vmctl console vnc ubuntu-vm
  vmctl console vnc ubuntu-vm --viewer vncviewer`,
		RunE: func(cmd *cobra.Command, args []string) error {
			vmName := args[0]
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			ProxyURL, WSPath, err := client.Console().GenerateConsoleURL(cmd.Context(), "vnc", connID, vmName)
			if err != nil {
				fmt.Println("get url error")
				return nil
			}

			fmt.Printf("VNC Console Information:\n")
			fmt.Printf("  Proxy URL: %s\n", ProxyURL)
			fmt.Printf("  WebSocket: %s\n", WSPath)
			fmt.Println()

			// 如果指定了查看器，启动它
			if viewer != "" {
				vncURL := ProxyURL
				fmt.Printf("Opening VNC viewer: %s %s\n", viewer, vncURL)

				cmd := exec.Command(viewer, vncURL)
				if err := cmd.Start(); err != nil {
					return fmt.Errorf("failed to start VNC viewer: %w", err)
				}

				fmt.Println("✓ VNC viewer launched")
			} else {
				fmt.Println("Use a VNC viewer to connect to the above URL")
				fmt.Println("Or use: vmctl console vnc <vm> --viewer vncviewer")
			}

			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "default", "Connection ID")
	cmd.Flags().StringVar(&viewer, "viewer", "vncviewer", "VNC viewer command (vncviewer, vinagre, etc.)")
	return cmd
}

// vmctl console spice <vm>
func newConsoleSPICECommand() *cobra.Command {
	var (
		connID string
		viewer string
	)

	cmd := &cobra.Command{
		Use:   "spice <vm-name>",
		Short: "Connect to SPICE console",
		Args:  cobra.ExactArgs(1),
		Long: `Connect to SPICE console using external viewer.

Requires a SPICE client to be installed:
  - remote-viewer (virt-viewer)
  - spicy (spice-gtk)`,
		Example: `  vmctl console spice ubuntu-vm
  vmctl console spice ubuntu-vm --viewer remote-viewer`,
		RunE: func(cmd *cobra.Command, args []string) error {
			vmName := args[0]
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			ProxyURL, WSPath, err := client.Console().GenerateConsoleURL(cmd.Context(), "spice", connID, vmName)
			if err != nil {
				fmt.Println("get url error")
				return nil
			}

			fmt.Printf("SPICE Console Information:\n")
			fmt.Printf("  Proxy URL: %s\n", ProxyURL)
			fmt.Printf("  WebSocket: %s\n", WSPath)
			fmt.Println()

			// 如果指定了查看器，启动它
			if viewer != "" {
				spiceURL := ProxyURL
				fmt.Printf("Opening SPICE viewer: %s %s\n", viewer, spiceURL)

				cmd := exec.Command(viewer, spiceURL)
				if err := cmd.Start(); err != nil {
					return fmt.Errorf("failed to start SPICE viewer: %w", err)
				}

				fmt.Println("✓ SPICE viewer launched")
			} else {
				fmt.Println("Use a SPICE client to connect to the above URL")
				fmt.Println("Or use: vmctl console spice <vm> --viewer remote-viewer")
			}

			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "default", "Connection ID")
	cmd.Flags().StringVar(&viewer, "viewer", "remote-viewer", "SPICE viewer command (remote-viewer, spicy, etc.)")
	return cmd
}
